Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regex loop for \K in lookbehind #14638

Closed
p5pRT opened this issue Apr 7, 2015 · 21 comments
Closed

Regex loop for \K in lookbehind #14638

p5pRT opened this issue Apr 7, 2015 · 21 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 7, 2015

Migrated from rt.perl.org#124256 (status was 'pending release')

Searchable as RT124256$

@p5pRT
Copy link
Author

p5pRT commented Apr 7, 2015

From ph10@hermes.cam.ac.uk

Created by ph10@hermes.cam.ac.uk

The command

perl -e 'while("aaaa" =~ /(?<=\Ka)/g){};'

puts Perl into an infinite loop. Without the \K in the assertion, it
finishes instantly. I think this is a similar bug to the one I have just
fixed in PCRE.

Regards,
Philip

--
Philip Hazel

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.20.2:

Configured by builduser at Mon Feb 16 15:25:02 CET 2015.

Summary of my perl5 (revision 5 version 20 subversion 2) configuration:
   
  Platform:
    osname=linux, osvers=3.19.0-1-arch, archname=x86_64-linux-thread-multi
    uname='linux flo-64 3.19.0-1-arch #1 smp preempt mon feb 9 07:08:20 cet 2015 x86_64 gnulinux '
    config_args='-des -Dusethreads -Duseshrplib -Doptimize=-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong --param=ssp-buffer-size=4 -Dprefix=/usr -Dvendorprefix=/usr -Dprivlib=/usr/share/perl5/core_perl -Darchlib=/usr/lib/perl5/core_perl -Dsitelib=/usr/share/perl5/site_perl -Dsitearch=/usr/lib/perl5/site_perl -Dvendorlib=/usr/share/perl5/vendor_perl -Dvendorarch=/usr/lib/perl5/vendor_perl -Dscriptdir=/usr/bin/core_perl -Dsitescript=/usr/bin/site_perl -Dvendorscript=/usr/bin/vendor_perl -Dinc_version_list=none -Dman1ext=1perl -Dman3ext=3perl -Dcccdlflags='-fPIC' -Dlddlflags=-shared -Wl,-O1,--sort-common,--as-needed,-z,relro -Dldflags=-Wl,-O1,--sort-common,--as-needed,-z,relro'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong --param=ssp-buffer-size=4',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.9.2 20150204 (prerelease)', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-Wl,-O1,--sort-common,--as-needed,-z,relro -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/include-fixed /usr/lib /lib/../lib /usr/lib/../lib /lib /lib64 /usr/lib64
    libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc -lgdbm_compat
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=libc-2.21.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.21'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/core_perl/CORE'
    cccdlflags='-fPIC', lddlflags='-shared -Wl,-O1,--sort-common,--as-needed,-z,relro -L/usr/local/lib -fstack-protector'



@INC for perl 5.20.2:
    /usr/lib/perl5/site_perl
    /usr/share/perl5/site_perl
    /usr/lib/perl5/vendor_perl
    /usr/share/perl5/vendor_perl
    /usr/lib/perl5/core_perl
    /usr/share/perl5/core_perl
    .


Environment for perl 5.20.2:
    HOME=/home/ph10
    LANG=en_GB
    LANGUAGE (unset)
    LC_ALL=C
    LC_COLLATE=C
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/ph10/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/usr/sbin:.
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2015

From @jkeenan

On Tue Apr 07 09​:46​:45 2015, ph10@​hermes.cam.ac.uk wrote​:

This is a bug report for perl from ph10@​hermes.cam.ac.uk,
generated with the help of perlbug 1.40 running under perl 5.20.2.

-----------------------------------------------------------------
[Please describe your issue here]

The command

perl -e 'while("aaaa" =~ /(?<=\Ka)/g){};'

puts Perl into an infinite loop. Without the \K in the assertion, it
finishes instantly.

A little diagnostic​:

#####
$ cat 124256-regex.pl
# perl
use strict;
use warnings;
use 5.10.1;

while ("aaaa" =~ /(?<=a)/g) {
  say "Yes​: <", join('|' => $`, $&amp;, $'), ">";
}

say '';

# Below​: Infinite loop
while ("aaaa" =~ /(?<=\Ka)/g) {
  say "Yes​: <", join('|' => $`, $&amp;, $'), ">";
}
#####

The top part produces​:

#####
Yes​: <a||aaa>
Yes​: <aa||aa>
Yes​: <aaa||a>
Yes​: <aaaa||>
#####

The bottom part loops forever, producing​:

#####
Yes​: <|a|aaa>
#####

I think this is a similar bug to the one I have just
fixed in PCRE.

Can you provide a link to that fix?

Thank you very much.

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2015

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2015

From @khwilliamson

I bisected this, and it appears that this bug has been there from the very first, so this is not a regression​:

ee9b8ea is the first bad commit
commit ee9b8ea
Author​: Yves Orton <demerphq@​gmail.com>
Date​: Wed Jan 10 21​:33​:39 2007 +0100

  Add Regexp​::Keep \K functionality to regex engine as well as add \v and \V, cleanup and more docs for regatom()
  Message-ID​: <9b18b3110701101133i46dc5fd0p1476a0f1dd1e9c5a@​mail.gmail.com>
 
  (plus POD nits by Merijn and myself)

--
Karl Williamson

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2015

From @khwilliamson

Also, -Dr output looks like
...
Compiling REx "(?<=\Ka)"
Final program​:
  1​: IFMATCH[-1] (8)
  3​: KEEPS (4)
  4​: EXACT <a> (6)
  6​: SUCCEED (0)
  7​: TAIL (8)
  8​: END (0)
minlen 0
Enabling $` $&amp; $' support (0x7).

EXECUTING...

Matching REx "(?<=\Ka)" against "aaaa"
  0 <> <aaaa> | 1​:IFMATCH[-1](8)
  failed...
  1 <a> <aaa> | 1​:IFMATCH[-1](8)
  0 <> <aaaa> | 3​: KEEPS(4)
  0 <> <aaaa> | 4​: EXACT <a>(6)
  1 <a> <aaa> | 6​: SUCCEED(0)
  subpattern success...
  1 <a> <aaa> | 8​:END(0)
Match successful!
Matching REx "(?<=\Ka)" against "aaa"
  1 <a> <aaa> | 1​:IFMATCH[-1](8)
  0 <> <aaaa> | 3​: KEEPS(4)
  0 <> <aaaa> | 4​: EXACT <a>(6)
  1 <a> <aaa> | 6​: SUCCEED(0)
  subpattern success...
  1 <a> <aaa> | 8​:END(0)
Match successful!
Matching REx "(?<=\Ka)" against "aaa"
  1 <a> <aaa> | 1​:IFMATCH[-1](8)
  0 <> <aaaa> | 3​: KEEPS(4)
  0 <> <aaaa> | 4​: EXACT <a>(6)
  1 <a> <aaa> | 6​: SUCCEED(0)
  subpattern success...
  1 <a> <aaa> | 8​:END(0)
Match successful!

ad infinitum
--
Karl Williamson

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2015

From ph10@hermes.cam.ac.uk

On Mon, 27 Apr 2015, James E Keenan via RT wrote​:

I think this is a similar bug to the one I have just
fixed in PCRE.

Can you provide a link to that fix?

Thank you very much.

Not very easily (I'd have to check the SVN manual to figure out how to
search for stuff - I'm a very simple user) and in any case the fix was
different for PCRE1 and PCRE2. The bug was in the test programs pcretest
and pcre2test rather than in the library itself (which only does single
matches). Here is a comment from pcre2test.c​:

  However, even after matching a non-empty string, there is still one
  tricky case. If a pattern contains \K within a lookbehind assertion at the
  start, the end of the matched string can be at the offset where the match
  started. In the case of a normal /g iteration without special action, this
  leads to a loop that keeps on returning the same substring.

The code now checks for this case and advances the /g loop by one
character, just as it does for matching an empty string.

Regards,
Philip

--
Philip Hazel

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2015

From @demerphq

On 28 April 2015 at 13​:14, <ph10@​hermes.cam.ac.uk> wrote​:

On Mon, 27 Apr 2015, James E Keenan via RT wrote​:

I think this is a similar bug to the one I have just
fixed in PCRE.

Can you provide a link to that fix?

Thank you very much.

Not very easily (I'd have to check the SVN manual to figure out how to
search for stuff - I'm a very simple user) and in any case the fix was
different for PCRE1 and PCRE2. The bug was in the test programs pcretest
and pcre2test rather than in the library itself (which only does single
matches). Here is a comment from pcre2test.c​:

However\, even after matching a non\-empty string\, there is still one
tricky case\. If a pattern contains \\K within a lookbehind assertion at the
start\, the end of the matched string can be at the offset where the match
started\. In the case of a normal /g iteration without special action\, this
leads to a loop that keeps on returning the same substring\.

The code now checks for this case and advances the /g loop by one
character, just as it does for matching an empty string.

Sounds like we have the same problem in Perl.

Karl, if you dont see a way to fix this then let me know and I will pick it up.

Cheers,
yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2015

From @khwilliamson

On 04/28/2015 06​:40 AM, demerphq wrote​:

On 28 April 2015 at 13​:14, <ph10@​hermes.cam.ac.uk> wrote​:

On Mon, 27 Apr 2015, James E Keenan via RT wrote​:

I think this is a similar bug to the one I have just
fixed in PCRE.

Can you provide a link to that fix?

Thank you very much.

Not very easily (I'd have to check the SVN manual to figure out how to
search for stuff - I'm a very simple user) and in any case the fix was
different for PCRE1 and PCRE2. The bug was in the test programs pcretest
and pcre2test rather than in the library itself (which only does single
matches). Here is a comment from pcre2test.c​:

 However\, even after matching a non\-empty string\, there is still one
 tricky case\. If a pattern contains \\K within a lookbehind assertion at the
 start\, the end of the matched string can be at the offset where the match
 started\. In the case of a normal /g iteration without special action\, this
 leads to a loop that keeps on returning the same substring\.

The code now checks for this case and advances the /g loop by one
character, just as it does for matching an empty string.

Sounds like we have the same problem in Perl.

Karl, if you dont see a way to fix this then let me know and I will pick it up.

Cheers,
yves

I haven't ever looked at the \K code; I was hoping someone else would
look at this.

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2015

From @demerphq

On 28 April 2015 at 22​:28, Karl Williamson <public@​khwilliamson.com> wrote​:

On 04/28/2015 06​:40 AM, demerphq wrote​:

On 28 April 2015 at 13​:14, <ph10@​hermes.cam.ac.uk> wrote​:

On Mon, 27 Apr 2015, James E Keenan via RT wrote​:

I think this is a similar bug to the one I have just
fixed in PCRE.

Can you provide a link to that fix?

Thank you very much.

Not very easily (I'd have to check the SVN manual to figure out how to
search for stuff - I'm a very simple user) and in any case the fix was
different for PCRE1 and PCRE2. The bug was in the test programs pcretest
and pcre2test rather than in the library itself (which only does single
matches). Here is a comment from pcre2test.c​:

 However\, even after matching a non\-empty string\, there is still one
 tricky case\. If a pattern contains \\K within a lookbehind assertion

at the
start, the end of the matched string can be at the offset where the
match
started. In the case of a normal /g iteration without special
action, this
leads to a loop that keeps on returning the same substring.

The code now checks for this case and advances the /g loop by one
character, just as it does for matching an empty string.

Sounds like we have the same problem in Perl.

Karl, if you dont see a way to fix this then let me know and I will pick
it up.

Cheers,
yves

I haven't ever looked at the \K code; I was hoping someone else would look
at this.

Ok, then I will try to find time to address this.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2015

From @khwilliamson

On 4/28/2015 3​:26 PM, demerphq wrote​:

On 28 April 2015 at 22​:28, Karl Williamson <public@​khwilliamson.com> wrote​:

On 04/28/2015 06​:40 AM, demerphq wrote​:

On 28 April 2015 at 13​:14, <ph10@​hermes.cam.ac.uk> wrote​:

On Mon, 27 Apr 2015, James E Keenan via RT wrote​:

I think this is a similar bug to the one I have just
fixed in PCRE.

Can you provide a link to that fix?

Thank you very much.

Not very easily (I'd have to check the SVN manual to figure out how to
search for stuff - I'm a very simple user) and in any case the fix was
different for PCRE1 and PCRE2. The bug was in the test programs pcretest
and pcre2test rather than in the library itself (which only does single
matches). Here is a comment from pcre2test.c​:

  However\, even after matching a non\-empty string\, there is still one
  tricky case\. If a pattern contains \\K within a lookbehind assertion

at the
start, the end of the matched string can be at the offset where the
match
started. In the case of a normal /g iteration without special
action, this
leads to a loop that keeps on returning the same substring.

The code now checks for this case and advances the /g loop by one
character, just as it does for matching an empty string.

Sounds like we have the same problem in Perl.

Karl, if you dont see a way to fix this then let me know and I will pick
it up.

Cheers,
yves

I haven't ever looked at the \K code; I was hoping someone else would look
at this.

Ok, then I will try to find time to address this.

Note that this is a 5.23 item, so there isn't a real urgency

@p5pRT
Copy link
Author

p5pRT commented May 27, 2015

From @tonycoz

On Tue Apr 28 14​:27​:34 2015, demerphq wrote​:

On 28 April 2015 at 22​:28, Karl Williamson <public@​khwilliamson.com> wrote​:

I haven't ever looked at the \K code; I was hoping someone else would look
at this.

Ok, then I will try to find time to address this.

What's the intended behaviour of \K in a look-(ahead|behind)?

My first thught was that it should be ignored, something like​:

--- a/regcomp.c
+++ b/regcomp.c
@​@​ -11787,15 +11787,23 @​@​ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp,
  *flagp |= SIMPLE;
  goto finish_meta_pat;
  case 'K'​:
- RExC_seen_zerolen++;
- ret = reg_node(pRExC_state, KEEPS);
- *flagp |= SIMPLE;
- /* XXX​:dmq : disabling in-place substitution seems to
- * be necessary here to avoid cases of memory corruption, as
- * with​: C<$_="x" x 80; s/x\K/y/> -- rgs
- */
- RExC_seen |= REG_LOOKBEHIND_SEEN;
- goto finish_meta_pat;
+ if (!RExC_in_lookbehind) {
+ RExC_seen_zerolen++;
+ ret = reg_node(pRExC_state, KEEPS);
+ *flagp |= SIMPLE;
+ /* XXX​:dmq : disabling in-place substitution seems to
+ * be necessary here to avoid cases of memory corruption, as
+ * with​: C<$_="x" x 80; s/x\K/y/> -- rgs
+ */
+ RExC_seen |= REG_LOOKBEHIND_SEEN;
+ goto finish_meta_pat;
+ }
+ else {
+ ++RExC_parse;
+ if (PASS2)
+ ckWARNreg(RExC_parse, "\\K useless in lookbehind");
+ goto tryagain;
+ }

(with some extra code needed to handle look-aheads.)

Or should it control the region matched, so \K in the example would set $& to "a",
as it does now?

Tony

@p5pRT
Copy link
Author

p5pRT commented May 27, 2015

From @ap

* Tony Cook via RT <perlbug-followup@​perl.org> [2015-05-27 07​:05]​:

What's the intended behaviour of \K in a look-(ahead|behind)?

My first thught was that it should be ignored, something like​:

Or should it control the region matched, so \K in the example would
set $& to "a", as it does now?

It seems to me like it can only really have reasonable semantics at the
“top level” of a match. It’s possible to invent more specific semantics
in other places, but everything I can think of is a stretch; they would
just be semantics invented for the sake of existing, not because they do
anything anyone wants.

So I would be most inclined to treat it as a compile error, at the least
inside lookarounds. Preferably also in any group – or maybe just inside
quantified groups.

I have, FWIW, used it plenty but never used it inside a group. Anyone?

Regards,
--
Aristotle Pagaltzis // <http​://plasmasturm.org/>

@p5pRT
Copy link
Author

p5pRT commented May 28, 2015

From @tonycoz

On Tue May 26 22​:03​:58 2015, tonyc wrote​:

On Tue Apr 28 14​:27​:34 2015, demerphq wrote​:

On 28 April 2015 at 22​:28, Karl Williamson <public@​khwilliamson.com>
wrote​:

I haven't ever looked at the \K code; I was hoping someone else
would look
at this.

Ok, then I will try to find time to address this.

What's the intended behaviour of \K in a look-(ahead|behind)?

My first thught was that it should be ignored, something like​:

Which was broken in at least one way.

Attached is a "better" patch, depending on how much I've managed
to mess up the regexp engine ;)

Tony

@p5pRT
Copy link
Author

p5pRT commented May 28, 2015

From @tonycoz

0001-prevent-K-working-in-lookahead-behind-assertions-and.patch
From 40f4dee6393db72c33d89117b6e092e4e349366c Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Thu, 28 May 2015 16:03:50 +1000
Subject: [PATCH] prevent \K working in lookahead/behind assertions (and warn)

this is probably incorrect, since I'm clueless about the regexp
engine

It may be that in_lookbehind and in_lookahead can be combined, since
in_lookbehind appears to be only used to maintain its own value.
---
 pod/perldiag.pod       |    5 +++++
 regcomp.c              |   51 +++++++++++++++++++++++++++++++++++++-----------
 t/lib/warnings/regcomp |   12 ++++++++++++
 t/re/pat_advanced.t    |   14 +++++++++++++
 4 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 93ae13b..fb00745 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -6556,6 +6556,11 @@ about the /d modifier.
 (W misc) You have a \E in a double-quotish string without a C<\U>,
 C<\L> or C<\Q> preceding it.
 
+=item Useless use of \K in lookbehind/lookahead in regex; marked by S<<-- HERE> in m/%s/
+
+(W regexp) Your regular expression used C<\K> in a lookhead or
+lookbehind assertion, where is has no effect.
+
 =item Useless use of greediness modifier '%c' in regex; marked by S<<-- HERE> in m/%s/
 
 (W regexp) You specified something like these:
diff --git a/regcomp.c b/regcomp.c
index 712c8ed7..945778d 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -177,6 +177,7 @@ struct RExC_state_t {
                                            through */
     U32         study_chunk_recursed_bytes;  /* bytes in bitmap */
     I32		in_lookbehind;
+    I32		in_lookahead;
     I32		contains_locale;
     I32		contains_i;
     I32		override_recoding;
@@ -255,6 +256,7 @@ struct RExC_state_t {
 #define RExC_study_chunk_recursed_bytes  \
                                    (pRExC_state->study_chunk_recursed_bytes)
 #define RExC_in_lookbehind	(pRExC_state->in_lookbehind)
+#define RExC_in_lookahead	(pRExC_state->in_lookahead)
 #define RExC_contains_locale	(pRExC_state->contains_locale)
 #define RExC_contains_i (pRExC_state->contains_i)
 #define RExC_override_recoding (pRExC_state->override_recoding)
@@ -6633,6 +6635,7 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
     RExC_seen = 0;
     RExC_maxlen = 0;
     RExC_in_lookbehind = 0;
+    RExC_in_lookahead = 0;
     RExC_seen_zerolen = *exp == '^' ? -1 : 0;
     RExC_extralen = 0;
     RExC_override_recoding = 0;
@@ -9782,6 +9785,12 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)
 
     *flagp = 0;				/* Tentatively. */
 
+    if (RExC_in_lookbehind) {
+	RExC_in_lookbehind++;
+    }
+    if (RExC_in_lookahead) {
+        RExC_in_lookahead++;
+    }
 
     /* Make an OPEN node, if parenthesized. */
     if (paren) {
@@ -10055,9 +10064,11 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)
                 RExC_seen |= REG_LOOKBEHIND_SEEN;
 		RExC_in_lookbehind++;
 		RExC_parse++;
-                /* FALLTHROUGH */
+                RExC_seen_zerolen++;
+                break;
 	    case '=':           /* (?=...) */
-		RExC_seen_zerolen++;
+		RExC_in_lookahead++;
+                RExC_seen_zerolen++;
                 break;
 	    case '!':           /* (?!...) */
 		RExC_seen_zerolen++;
@@ -10685,6 +10696,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)
     if (RExC_in_lookbehind) {
 	RExC_in_lookbehind--;
     }
+    if (RExC_in_lookahead) {
+        RExC_in_lookahead--;
+    }
     if (after_freeze > RExC_npar)
         RExC_npar = after_freeze;
     return(ret);
@@ -11787,15 +11801,30 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
 	    *flagp |= SIMPLE;
 	    goto finish_meta_pat;
 	case 'K':
-	    RExC_seen_zerolen++;
-	    ret = reg_node(pRExC_state, KEEPS);
-	    *flagp |= SIMPLE;
-	    /* XXX:dmq : disabling in-place substitution seems to
-	     * be necessary here to avoid cases of memory corruption, as
-	     * with: C<$_="x" x 80; s/x\K/y/> -- rgs
-	     */
-            RExC_seen |= REG_LOOKBEHIND_SEEN;
-	    goto finish_meta_pat;
+            if (!RExC_in_lookbehind && !RExC_in_lookahead) {
+                RExC_seen_zerolen++;
+                ret = reg_node(pRExC_state, KEEPS);
+                *flagp |= SIMPLE;
+                /* XXX:dmq : disabling in-place substitution seems to
+                 * be necessary here to avoid cases of memory corruption, as
+                 * with: C<$_="x" x 80; s/x\K/y/> -- rgs
+                 */
+                RExC_seen |= REG_LOOKBEHIND_SEEN;
+            }
+            else {
+                if (PASS2) {
+                    /* adjust offset so <-- points at the K */
+                    ++RExC_parse;
+                    ckWARNreg(RExC_parse, "Useless use of \\K in lookbehind/lookahead");
+                    --RExC_parse;
+                }
+                /* originally I did goto tryagain here, but that failed
+                 * with an Internal urp when a ) immediately followed the \K.
+                 * So return something, even if it's NOTHING.
+                 */
+                ret = reg_node(pRExC_state, NOTHING);
+            }
+            goto finish_meta_pat;
 	case 'Z':
 	    ret = reg_node(pRExC_state, SEOL);
 	    *flagp |= SIMPLE;
diff --git a/t/lib/warnings/regcomp b/t/lib/warnings/regcomp
index b9943a0..9d569cd 100644
--- a/t/lib/warnings/regcomp
+++ b/t/lib/warnings/regcomp
@@ -36,3 +36,15 @@ $a = qr/[\c,]/;
 EXPECT
 "\c," is more clearly written simply as "l" at - line 9.
 "\c," is more clearly written simply as "l" at - line 10.
+########
+# regcomp.c - \K in assertion
+use warnings;
+$x = "aaaa";
+$x =~ /(?<=\Ka)/;
+$x =~ /(?=a\Ka)aa/;
+no warnings 'regexp';
+$x =~ /(?<=\Ka)/;
+$x =~ /(?=a\Ka)aa/;
+EXPECT
+Useless use of \K in lookbehind/lookahead in regex; marked by <-- HERE in m/(?<=\K <-- HERE a)/ at - line 4.
+Useless use of \K in lookbehind/lookahead in regex; marked by <-- HERE in m/(?=a\K <-- HERE a)aa/ at - line 5.
diff --git a/t/re/pat_advanced.t b/t/re/pat_advanced.t
index 891bb66..d8d5823 100644
--- a/t/re/pat_advanced.t
+++ b/t/re/pat_advanced.t
@@ -1498,6 +1498,20 @@ sub run_tests {
         $x = "abcde";
         $x =~ s/(.)\K/$1/g;
         is($x, "aabbccddee", $message);
+
+        no warnings 'regexp';
+        $x = "aaaa";
+        $x =~ /(?<=\Ka)/;
+        is($&, "", "\\K in lookbehind meaningless");
+
+        $x =~ /(?<=(a)\K)/;
+        is($&, "", "\\K in lookbehind meaningless (with nesting)");
+
+        $x =~ /(?=a\Ka)aa/;
+        is($&, "aa", "\\K in lookahead meaningless");
+
+        $x =~ /(?=(a)\Ka)aa/;
+        is($&, "aa", "\\K in lookahead meaningless (nesting)");
     }
 
     {
-- 
1.7.10.4

@p5pRT
Copy link
Author

p5pRT commented May 28, 2015

From @Tux

On Wed, 27 May 2015 23​:05​:34 -0700, "Tony Cook via RT"
<perlbug-followup@​perl.org> wrote​:

- RExC_seen_zerolen++;
+ RExC_in_lookahead++;
+ RExC_seen_zerolen++;

that looks like inconsistent indentation

--
H.Merijn Brand http​://tux.nl Perl Monger http​://amsterdam.pm.org/
using perl5.00307 .. 5.21 porting perl5 on HP-UX, AIX, and openSUSE
http​://mirrors.develooper.com/hpux/ http​://www.test-smoke.org/
http​://qa.perl.org http​://www.goldmark.org/jeff/stupid-disclaimers/

@p5pRT
Copy link
Author

p5pRT commented Dec 9, 2015

From @jkeenan

On Wed May 27 23​:17​:14 2015, hmbrand wrote​:

On Wed, 27 May 2015 23​:05​:34 -0700, "Tony Cook via RT"
<perlbug-followup@​perl.org> wrote​:

- RExC_seen_zerolen++;
+ RExC_in_lookahead++;
+ RExC_seen_zerolen++;

that looks like inconsistent indentation

Contributors to this RT​: Do we have any more ideas on how to proceed further?

Thank you very much.
--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Dec 10, 2015

From @hvds

On Wed Dec 09 15​:49​:38 2015, jkeenan wrote​:

Contributors to this RT​: Do we have any more ideas on how to proceed
further?

I think someone with regexp-engine knowledge needs to review the patch; ideally that would be Yves. If he doesn't have time, I can try to do this - it'll take a while, since I'm not yet familiar with the use or implementation of \K, but I should have some free time over the Christmas period.

Hugo

@p5pRT
Copy link
Author

p5pRT commented Dec 10, 2015

From @demerphq

While I have not tested it the patch looks fine to me. I have to admit
to feeling stupid reading it actually. It didn't occur to me to simply
forbid \K inside of lookaround, and it is a simple solution which
leaves the option of allowing it in the future if we can figure out
what it should mean and how it should work. So ++ to you Tony.

Yves

On 28 May 2015 at 08​:05, Tony Cook via RT <perlbug-followup@​perl.org> wrote​:

On Tue May 26 22​:03​:58 2015, tonyc wrote​:

On Tue Apr 28 14​:27​:34 2015, demerphq wrote​:

On 28 April 2015 at 22​:28, Karl Williamson <public@​khwilliamson.com>
wrote​:

I haven't ever looked at the \K code; I was hoping someone else
would look
at this.

Ok, then I will try to find time to address this.

What's the intended behaviour of \K in a look-(ahead|behind)?

My first thught was that it should be ignored, something like​:

Which was broken in at least one way.

Attached is a "better" patch, depending on how much I've managed
to mess up the regexp engine ;)

Tony

---
via perlbug​: queue​: perl5 status​: open
https://rt-archive.perl.org/perl5/Ticket/Display.html?id=124256

From 40f4dee6393db72c33d89117b6e092e4e349366c Mon Sep 17 00​:00​:00 2001
From​: Tony Cook <tony@​develop-help.com>
Date​: Thu, 28 May 2015 16​:03​:50 +1000
Subject​: [PATCH] prevent \K working in lookahead/behind assertions (and warn)

this is probably incorrect, since I'm clueless about the regexp
engine

It may be that in_lookbehind and in_lookahead can be combined, since
in_lookbehind appears to be only used to maintain its own value.
---
pod/perldiag.pod | 5 +++++
regcomp.c | 51 +++++++++++++++++++++++++++++++++++++-----------
t/lib/warnings/regcomp | 12 ++++++++++++
t/re/pat_advanced.t | 14 +++++++++++++
4 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 93ae13b..fb00745 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@​@​ -6556,6 +6556,11 @​@​ about the /d modifier.
(W misc) You have a \E in a double-quotish string without a C<\U>,
C<\L> or C<\Q> preceding it.

+=item Useless use of \K in lookbehind/lookahead in regex; marked by S<<-- HERE> in m/%s/
+
+(W regexp) Your regular expression used C<\K> in a lookhead or
+lookbehind assertion, where is has no effect.
+
=item Useless use of greediness modifier '%c' in regex; marked by S<<-- HERE> in m/%s/

(W regexp) You specified something like these​:
diff --git a/regcomp.c b/regcomp.c
index 712c8ed7..945778d 100644
--- a/regcomp.c
+++ b/regcomp.c
@​@​ -177,6 +177,7 @​@​ struct RExC_state_t {
through */
U32 study_chunk_recursed_bytes; /* bytes in bitmap */
I32 in_lookbehind;
+ I32 in_lookahead;
I32 contains_locale;
I32 contains_i;
I32 override_recoding;
@​@​ -255,6 +256,7 @​@​ struct RExC_state_t {
#define RExC_study_chunk_recursed_bytes \
(pRExC_state->study_chunk_recursed_bytes)
#define RExC_in_lookbehind (pRExC_state->in_lookbehind)
+#define RExC_in_lookahead (pRExC_state->in_lookahead)
#define RExC_contains_locale (pRExC_state->contains_locale)
#define RExC_contains_i (pRExC_state->contains_i)
#define RExC_override_recoding (pRExC_state->override_recoding)
@​@​ -6633,6 +6635,7 @​@​ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
RExC_seen = 0;
RExC_maxlen = 0;
RExC_in_lookbehind = 0;
+ RExC_in_lookahead = 0;
RExC_seen_zerolen = *exp == '^' ? -1 : 0;
RExC_extralen = 0;
RExC_override_recoding = 0;
@​@​ -9782,6 +9785,12 @​@​ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)

 \*flagp = 0;                                /\* Tentatively\. \*/

+ if (RExC_in_lookbehind) {
+ RExC_in_lookbehind++;
+ }
+ if (RExC_in_lookahead) {
+ RExC_in_lookahead++;
+ }

 /\* Make an OPEN node\, if parenthesized\. \*/
 if \(paren\) \{

@​@​ -10055,9 +10064,11 @​@​ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)
RExC_seen |= REG_LOOKBEHIND_SEEN;
RExC_in_lookbehind++;
RExC_parse++;
- /* FALLTHROUGH */
+ RExC_seen_zerolen++;
+ break;
case '='​: /* (?=...) */
- RExC_seen_zerolen++;
+ RExC_in_lookahead++;
+ RExC_seen_zerolen++;
break;
case '!'​: /* (?!...) */
RExC_seen_zerolen++;
@​@​ -10685,6 +10696,9 @​@​ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)
if (RExC_in_lookbehind) {
RExC_in_lookbehind--;
}
+ if (RExC_in_lookahead) {
+ RExC_in_lookahead--;
+ }
if (after_freeze > RExC_npar)
RExC_npar = after_freeze;
return(ret);
@​@​ -11787,15 +11801,30 @​@​ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
*flagp |= SIMPLE;
goto finish_meta_pat;
case 'K'​:
- RExC_seen_zerolen++;
- ret = reg_node(pRExC_state, KEEPS);
- *flagp |= SIMPLE;
- /* XXX​:dmq : disabling in-place substitution seems to
- * be necessary here to avoid cases of memory corruption, as
- * with​: C<$_="x" x 80; s/x\K/y/> -- rgs
- */
- RExC_seen |= REG_LOOKBEHIND_SEEN;
- goto finish_meta_pat;
+ if (!RExC_in_lookbehind && !RExC_in_lookahead) {
+ RExC_seen_zerolen++;
+ ret = reg_node(pRExC_state, KEEPS);
+ *flagp |= SIMPLE;
+ /* XXX​:dmq : disabling in-place substitution seems to
+ * be necessary here to avoid cases of memory corruption, as
+ * with​: C<$_="x" x 80; s/x\K/y/> -- rgs
+ */
+ RExC_seen |= REG_LOOKBEHIND_SEEN;
+ }
+ else {
+ if (PASS2) {
+ /* adjust offset so <-- points at the K */
+ ++RExC_parse;
+ ckWARNreg(RExC_parse, "Useless use of \\K in lookbehind/lookahead");
+ --RExC_parse;
+ }
+ /* originally I did goto tryagain here, but that failed
+ * with an Internal urp when a ) immediately followed the \K.
+ * So return something, even if it's NOTHING.
+ */
+ ret = reg_node(pRExC_state, NOTHING);
+ }
+ goto finish_meta_pat;
case 'Z'​:
ret = reg_node(pRExC_state, SEOL);
*flagp |= SIMPLE;
diff --git a/t/lib/warnings/regcomp b/t/lib/warnings/regcomp
index b9943a0..9d569cd 100644
--- a/t/lib/warnings/regcomp
+++ b/t/lib/warnings/regcomp
@​@​ -36,3 +36,15 @​@​ $a = qr/[\c,]/;
EXPECT
"\c," is more clearly written simply as "l" at - line 9.
"\c," is more clearly written simply as "l" at - line 10.
+########
+# regcomp.c - \K in assertion
+use warnings;
+$x = "aaaa";
+$x =~ /(?<=\Ka)/;
+$x =~ /(?=a\Ka)aa/;
+no warnings 'regexp';
+$x =~ /(?<=\Ka)/;
+$x =~ /(?=a\Ka)aa/;
+EXPECT
+Useless use of \K in lookbehind/lookahead in regex; marked by <-- HERE in m/(?<=\K <-- HERE a)/ at - line 4.
+Useless use of \K in lookbehind/lookahead in regex; marked by <-- HERE in m/(?=a\K <-- HERE a)aa/ at - line 5.
diff --git a/t/re/pat_advanced.t b/t/re/pat_advanced.t
index 891bb66..d8d5823 100644
--- a/t/re/pat_advanced.t
+++ b/t/re/pat_advanced.t
@​@​ -1498,6 +1498,20 @​@​ sub run_tests {
$x = "abcde";
$x =~ s/(.)\K/$1/g;
is($x, "aabbccddee", $message);
+
+ no warnings 'regexp';
+ $x = "aaaa";
+ $x =~ /(?<=\Ka)/;
+ is($&, "", "\\K in lookbehind meaningless");
+
+ $x =~ /(?<=(a)\K)/;
+ is($&, "", "\\K in lookbehind meaningless (with nesting)");
+
+ $x =~ /(?=a\Ka)aa/;
+ is($&, "aa", "\\K in lookahead meaningless");
+
+ $x =~ /(?=(a)\Ka)aa/;
+ is($&, "aa", "\\K in lookahead meaningless (nesting)");
}

 \{

--
1.7.10.4

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Aug 6, 2016

From @khwilliamson

On Thu Dec 10 03​:37​:21 2015, demerphq wrote​:

While I have not tested it the patch looks fine to me. I have to admit
to feeling stupid reading it actually. It didn't occur to me to simply
forbid \K inside of lookaround, and it is a simple solution which
leaves the option of allowing it in the future if we can figure out
what it should mean and how it should work. So ++ to you Tony.

Yves

On 28 May 2015 at 08​:05, Tony Cook via RT <perlbug-followup@​perl.org>
wrote​:

On Tue May 26 22​:03​:58 2015, tonyc wrote​:

On Tue Apr 28 14​:27​:34 2015, demerphq wrote​:

On 28 April 2015 at 22​:28, Karl Williamson
<public@​khwilliamson.com>
wrote​:

I haven't ever looked at the \K code; I was hoping someone else
would look
at this.

Ok, then I will try to find time to address this.

What's the intended behaviour of \K in a look-(ahead|behind)?

My first thught was that it should be ignored, something like​:

Which was broken in at least one way.

Attached is a "better" patch, depending on how much I've managed
to mess up the regexp engine ;)

Tony

---
via perlbug​: queue​: perl5 status​: open
https://rt-archive.perl.org/perl5/Ticket/Display.html?id=124256

From 40f4dee6393db72c33d89117b6e092e4e349366c Mon Sep 17 00​:00​:00
2001
From​: Tony Cook <tony@​develop-help.com>
Date​: Thu, 28 May 2015 16​:03​:50 +1000
Subject​: [PATCH] prevent \K working in lookahead/behind assertions
(and warn)

this is probably incorrect, since I'm clueless about the regexp
engine

It may be that in_lookbehind and in_lookahead can be combined, since
in_lookbehind appears to be only used to maintain its own value.
---
pod/perldiag.pod | 5 +++++
regcomp.c | 51
+++++++++++++++++++++++++++++++++++++-----------
t/lib/warnings/regcomp | 12 ++++++++++++
t/re/pat_advanced.t | 14 +++++++++++++
4 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 93ae13b..fb00745 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@​@​ -6556,6 +6556,11 @​@​ about the /d modifier.
(W misc) You have a \E in a double-quotish string without a C<\U>,
C<\L> or C<\Q> preceding it.

+=item Useless use of \K in lookbehind/lookahead in regex; marked by
S<<-- HERE> in m/%s/
+
+(W regexp) Your regular expression used C<\K> in a lookhead or
+lookbehind assertion, where is has no effect.
+
=item Useless use of greediness modifier '%c' in regex; marked by
S<<-- HERE> in m/%s/

(W regexp) You specified something like these​:
diff --git a/regcomp.c b/regcomp.c
index 712c8ed7..945778d 100644
--- a/regcomp.c
+++ b/regcomp.c
@​@​ -177,6 +177,7 @​@​ struct RExC_state_t {
through */
U32 study_chunk_recursed_bytes; /* bytes in bitmap */
I32 in_lookbehind;
+ I32 in_lookahead;
I32 contains_locale;
I32 contains_i;
I32 override_recoding;
@​@​ -255,6 +256,7 @​@​ struct RExC_state_t {
#define RExC_study_chunk_recursed_bytes \
(pRExC_state-

study_chunk_recursed_bytes)
#define RExC_in_lookbehind (pRExC_state->in_lookbehind)
+#define RExC_in_lookahead (pRExC_state->in_lookahead)
#define RExC_contains_locale (pRExC_state->contains_locale)
#define RExC_contains_i (pRExC_state->contains_i)
#define RExC_override_recoding (pRExC_state->override_recoding)
@​@​ -6633,6 +6635,7 @​@​ Perl_re_op_compile(pTHX_ SV ** const patternp,
int pat_count,
RExC_seen = 0;
RExC_maxlen = 0;
RExC_in_lookbehind = 0;
+ RExC_in_lookahead = 0;
RExC_seen_zerolen = *exp == '^' ? -1 : 0;
RExC_extralen = 0;
RExC_override_recoding = 0;
@​@​ -9782,6 +9785,12 @​@​ S_reg(pTHX_ RExC_state_t *pRExC_state, I32
paren, I32 *flagp,U32 depth)

*flagp = 0; /* Tentatively. */

+ if (RExC_in_lookbehind) {
+ RExC_in_lookbehind++;
+ }
+ if (RExC_in_lookahead) {
+ RExC_in_lookahead++;
+ }

/* Make an OPEN node, if parenthesized. */
if (paren) {
@​@​ -10055,9 +10064,11 @​@​ S_reg(pTHX_ RExC_state_t *pRExC_state, I32
paren, I32 *flagp,U32 depth)
RExC_seen |= REG_LOOKBEHIND_SEEN;
RExC_in_lookbehind++;
RExC_parse++;
- /* FALLTHROUGH */
+ RExC_seen_zerolen++;
+ break;
case '='​: /* (?=...) */
- RExC_seen_zerolen++;
+ RExC_in_lookahead++;
+ RExC_seen_zerolen++;
break;
case '!'​: /* (?!...) */
RExC_seen_zerolen++;
@​@​ -10685,6 +10696,9 @​@​ S_reg(pTHX_ RExC_state_t *pRExC_state, I32
paren, I32 *flagp,U32 depth)
if (RExC_in_lookbehind) {
RExC_in_lookbehind--;
}
+ if (RExC_in_lookahead) {
+ RExC_in_lookahead--;
+ }
if (after_freeze > RExC_npar)
RExC_npar = after_freeze;
return(ret);
@​@​ -11787,15 +11801,30 @​@​ S_regatom(pTHX_ RExC_state_t *pRExC_state,
I32 *flagp, U32 depth)
*flagp |= SIMPLE;
goto finish_meta_pat;
case 'K'​:
- RExC_seen_zerolen++;
- ret = reg_node(pRExC_state, KEEPS);
- *flagp |= SIMPLE;
- /* XXX​:dmq : disabling in-place substitution seems to
- * be necessary here to avoid cases of memory corruption,
as
- * with​: C<$_="x" x 80; s/x\K/y/> -- rgs
- */
- RExC_seen |= REG_LOOKBEHIND_SEEN;
- goto finish_meta_pat;
+ if (!RExC_in_lookbehind && !RExC_in_lookahead) {
+ RExC_seen_zerolen++;
+ ret = reg_node(pRExC_state, KEEPS);
+ *flagp |= SIMPLE;
+ /* XXX​:dmq : disabling in-place substitution seems
to
+ * be necessary here to avoid cases of memory
corruption, as
+ * with​: C<$_="x" x 80; s/x\K/y/> -- rgs
+ */
+ RExC_seen |= REG_LOOKBEHIND_SEEN;
+ }
+ else {
+ if (PASS2) {
+ /* adjust offset so <-- points at the K */
+ ++RExC_parse;
+ ckWARNreg(RExC_parse, "Useless use of \\K in
lookbehind/lookahead");
+ --RExC_parse;
+ }
+ /* originally I did goto tryagain here, but that
failed
+ * with an Internal urp when a ) immediately
followed the \K.
+ * So return something, even if it's NOTHING.
+ */
+ ret = reg_node(pRExC_state, NOTHING);
+ }
+ goto finish_meta_pat;
case 'Z'​:
ret = reg_node(pRExC_state, SEOL);
*flagp |= SIMPLE;
diff --git a/t/lib/warnings/regcomp b/t/lib/warnings/regcomp
index b9943a0..9d569cd 100644
--- a/t/lib/warnings/regcomp
+++ b/t/lib/warnings/regcomp
@​@​ -36,3 +36,15 @​@​ $a = qr/[\c,]/;
EXPECT
"\c," is more clearly written simply as "l" at - line 9.
"\c," is more clearly written simply as "l" at - line 10.
+########
+# regcomp.c - \K in assertion
+use warnings;
+$x = "aaaa";
+$x =~ /(?<=\Ka)/;
+$x =~ /(?=a\Ka)aa/;
+no warnings 'regexp';
+$x =~ /(?<=\Ka)/;
+$x =~ /(?=a\Ka)aa/;
+EXPECT
+Useless use of \K in lookbehind/lookahead in regex; marked by <--
HERE in m/(?<=\K <-- HERE a)/ at - line 4.
+Useless use of \K in lookbehind/lookahead in regex; marked by <--
HERE in m/(?=a\K <-- HERE a)aa/ at - line 5.
diff --git a/t/re/pat_advanced.t b/t/re/pat_advanced.t
index 891bb66..d8d5823 100644
--- a/t/re/pat_advanced.t
+++ b/t/re/pat_advanced.t
@​@​ -1498,6 +1498,20 @​@​ sub run_tests {
$x = "abcde";
$x =~ s/(.)\K/$1/g;
is($x, "aabbccddee", $message);
+
+ no warnings 'regexp';
+ $x = "aaaa";
+ $x =~ /(?<=\Ka)/;
+ is($&, "", "\\K in lookbehind meaningless");
+
+ $x =~ /(?<=(a)\K)/;
+ is($&, "", "\\K in lookbehind meaningless (with nesting)");
+
+ $x =~ /(?=a\Ka)aa/;
+ is($&, "aa", "\\K in lookahead meaningless");
+
+ $x =~ /(?=(a)\Ka)aa/;
+ is($&, "aa", "\\K in lookahead meaningless (nesting)");
}

{
--
1.7.10.4

Tony, It looks to me like you can apply this patch, with a possible watchdog-timer test as well
--
Karl Williamson

@p5pRT
Copy link
Author

p5pRT commented Aug 19, 2019

From @tonycoz

On Sat, 06 Aug 2016 16​:44​:36 -0700, khw wrote​:

Tony, It looks to me like you can apply this patch, with a possible
watchdog-timer test as well

Applied as 105c827, I haven't added a watchdog test, since the code doesn't get to that point anymore (the tests don't check against a string that would loop)

Tony

@p5pRT
Copy link
Author

p5pRT commented Aug 19, 2019

@tonycoz - Status changed from 'open' to 'pending release'

@p5pRT p5pRT closed this as completed Aug 19, 2019
tonycoz added a commit to tonycoz/perl5 that referenced this issue Oct 19, 2020
It was disallowed because:

- it was breaking things (GH Perl#14638)

- at the time, no-one had the tuits and knowledge to select non-buggy
  semantics and implement them.
tonycoz added a commit that referenced this issue Nov 4, 2020
It was disallowed because:

- it was breaking things (GH #14638)

- at the time, no-one had the tuits and knowledge to select non-buggy
  semantics and implement them.
steve-m-hay pushed a commit that referenced this issue Jan 6, 2021
It was disallowed because:

- it was breaking things (GH #14638)

- at the time, no-one had the tuits and knowledge to select non-buggy
  semantics and implement them.

(cherry picked from commit 55afc78)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant